package com.xy.exam.service.impl;

import com.alibaba.fastjson.JSON;
import com.xy.exam.Exception.ServiceException;
import com.xy.exam.dao.mapper.UserMapper;
import com.xy.exam.pojo.dto.UserAddNewDTO;
import com.xy.exam.pojo.dto.UserLoginDTO;
import com.xy.exam.pojo.dto.UserUpdateDTO;
import com.xy.exam.pojo.entity.User;
import com.xy.exam.pojo.vo.UserListItemVO;
import com.xy.exam.pojo.vo.UserStandardVO;
import com.xy.exam.security.AdminDetails;
import com.xy.exam.service.IUserService;
import com.xy.exam.web.ServiceCode;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class UserServiceImpl implements IUserService {


    @Value("${csmall.jwt.secret-key}")
    private String secretKey;
    @Value("${csmall.jwt.duration-in-minute}")
    private long durationInMinute;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    UserMapper userMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public String login(UserLoginDTO userLoginDTO) {
        log.debug("开始处理【管理员登录】的业务，参数：{}", userLoginDTO);
        // 创建认证信息对象
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                userLoginDTO.getUsername(), userLoginDTO.getPassword());
        log.debug("创建认证信息对象的authentication为：{}", authentication);
        // 调用认证管理器执行认证
        Authentication authenticationResult
                = authenticationManager.authenticate(authentication);
        log.debug("验证登录成功，返回的AuthenticationResult为：{}", authenticationResult);
        // 如果没有出现异常，则表示验证登录成功，需要将认证信息存入到Security上下文
        // log.debug("即将向SecurityContext中存入Authentication");
        // SecurityContext securityContext = SecurityContextHolder.getContext();
        // securityContext.setAuthentication(authenticationResult);
        // 处理验证登录成功后的结果中的当事人
        Object principal = authenticationResult.getPrincipal();
        log.debug("获取验证登录成功后的结果中的当事人：{}", principal);
        AdminDetails adminDetails = (AdminDetails) principal;

        // 需要写入到JWT中的数据
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", adminDetails.getId());
        claims.put("username", adminDetails.getUsername());
        String authoritiesJsonString = JSON.toJSONString(adminDetails.getAuthorities());
        claims.put("authoritiesJsonString", authoritiesJsonString);
        log.debug("即将生成JWT数据，包含的账号信息：{}", claims);

        // 生成JWT，并返回JWT
        Date exp = new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000);
        String jwt = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                .setClaims(claims)
                .setExpiration(exp)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("生成了JWT数据，并将返回此JWT数据：{}", jwt);
        return jwt;
    }

    @Override
    public void addNew(UserAddNewDTO userAddNewDTO) {
        //获取参数对象中的名称
        String username = userAddNewDTO.getUsername();
        //查询该名称对象是否存在,返回受影响行数
        int rows = userMapper.countByName(username);
        if (rows >0) {
            String message = "添加用户名失败,该用户名已经存在";
            throw new ServiceException(ServiceCode.ERR_CONFLICT,message);
        }
        //密码加密
        String encode = passwordEncoder.encode(userAddNewDTO.getPassword());
        log.debug("encode:{}",encode);
        userAddNewDTO.setPassword(encode);
        User user = new User();
        //获取当前系统时间的时间戳
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        user.setEnable(1);
        BeanUtils.copyProperties(userAddNewDTO, user);
        int insert = userMapper.insert(user);
        if (insert != 1) {
            String message = "添加用户名失败,服务器忙，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERR_INSERT,message);
        }
    }

    @Override
    public void delete(Long id) {
        UserStandardVO queryResult = userMapper.getStandardById(id);
        if (queryResult == null) {
            String message = "删除用户失败，尝试访问的数据不存在！";
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        int rows = userMapper.deleteById(id);
        if (rows != 1) {
            String message = "删除用户失败，服务器忙，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }
    }

    @Override
    public void updateInfoById(Long id, UserUpdateDTO userUpdateDTO) {
        UserStandardVO queryResult = userMapper.getStandardById(id);
        if (queryResult == null) {
            String message = "修改用户详情失败，尝试访问的数据不存在！";
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        String name = userUpdateDTO.getUsername();
        int count = userMapper.countByNameAndNotId(id, name);
        if (count > 0) {
            String message = "修改用户详情失败，用户名称已经被占用！";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        User user = new User();
        user.setUpdateTime(new Date());
        user.setId(id);
        BeanUtils.copyProperties(userUpdateDTO, user);
        int rows = userMapper.update(user);
        if (rows != 1) {
            String message = "修改用户详情失败，服务器忙，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    @Override
    public void setEnable(Long id) {
        updateEnableById(id, 1);
    }

    @Override
    public void setDisable(Long id) {
        updateEnableById(id, 0);
    }

    private void updateEnableById(Long id, Integer enable) {
        // 调用Mapper的查询，检查获取用户是否存在
        UserStandardVO standardById = userMapper.getStandardById(id);
        if (standardById == null) {
            String message = ENABLE_TEXT[enable] + "获取用户失败，尝试访问的数据不存在！";
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        // 检查当前获取用户的启用状态，如果与参数的目标状态相同，则抛出异常
        if (standardById.getEnable() == enable) {
            String message = ENABLE_TEXT[enable] + "获取用户失败，当前获取用户已经处于【" + ENABLE_TEXT[enable] + "】状态！";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        // 调用Mapper对象执行修改，更新获取用户的启用状态
        User user = new User();
        user.setId(id);
        user.setEnable(enable);
        int rows = userMapper.update(user);
        if (rows != 1) {
            String message = ENABLE_TEXT[enable] + "获取用户失败，，服务器忙，请稍后再尝试！";
            throw new ServiceException(ServiceCode.ERR_UPDATE, message);
        }
    }

    @Override
    public UserStandardVO getStandardById(Long id) {
        UserStandardVO queryResult = userMapper.getStandardById(id);
        if (queryResult == null) {
            String message = "获取用户详情失败，尝试访问的数据不存在！";
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }

        return queryResult;
    }

    @Override
    public List<UserListItemVO> list() {
        List<UserListItemVO> list = userMapper.list();
        return list;
    }
}
